/**
 *Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 *File Name: DownloadThread.java
 *Date: 2012-1-18
 *Copyright: All right reserved by author - Jiangtao He
 *Version: MyJavaExpert v1.0
 */
package com.ross.httpdownload;

import java.io.*;
import java.net.*;
import java.text.*;
import java.util.Date;

import com.ross.httpdownload.util.*;

/**
 * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
 * Date: 2012-1-18
 * Since: MyJavaExpert v1.0
 * Description: download thread implementation.
 */
public class DownloadThread implements Runnable
{
    private String sFileURL;
    private long lStartIndex;
    private long lEndIndex;
    private int iThreadId;
    private String sFullFileName;
    private HttpProcess oHttpProcess;

    /**
     * Description: default constructor, it is used for initializing the fields.
     */
    public DownloadThread()
    {
        oHttpProcess = new HttpProcess();
    }

    /**
     * Author: Jiangtao He; Email: ross.jiangtao.he@gmail.com
     * Description: it will implement the download logic
     */
    public void run()
    {
        System.out.println("The download thread "
                + this.iThreadId
                + " is started at "
                + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                        .format(new Date()));
        System.out.println("The download index of " + this.iThreadId + " is "
                + this.lStartIndex + " to " + this.lEndIndex);

        // content length
        long lContentlen = 0;
        // used to store the new url connection
        URLConnection oURLCon = null;
        // used to store the input stream of the response
        BufferedInputStream oBIn = null;
        // used to store the output writer
        RandomAccessFile oRAFile = null;
        // create the buffer
        byte[] bBuffer = new byte[SysValue.Buffer_Size];

        // get URL connection
        try
        {
            // create a link for each thread
            oURLCon = oHttpProcess.getURLConnection(this.sFileURL);
            // allow the user interaction, for example: a verify pop window
            oURLCon.setAllowUserInteraction(true);
            // set the resource range
            oURLCon.setRequestProperty("Range", "bytes=" + this.lStartIndex
                    + "-" + this.lEndIndex);

            // get the url connection input stream
            oBIn = new BufferedInputStream(oURLCon.getInputStream());
 
            // initialize the random access file object
            oRAFile = new RandomAccessFile(this.sFullFileName, "rw"); 
            oRAFile.seek(this.lStartIndex);

            // read the stream from http connection
            int iLen = 0;
            int iActualLen = 0;
            while (iActualLen < (this.lEndIndex - this.lStartIndex + 1))
            {
                iLen = oBIn.read(bBuffer, 0, SysValue.Buffer_Size);
                if (-1 == iLen)
                {
                    break;
                }

                // write the read data to file
                oRAFile.write(bBuffer, 0, iLen);

                // move the position mark
                iActualLen = iActualLen + iLen;
            }
            System.out.println("Thread " + this.iThreadId
                    + " download is finished, totaly: " + iActualLen);
        }
        catch (IOException e)
        {
            System.out.println("download the file failed, IO Exception"
                    + e.getMessage());
            e.printStackTrace();
        }
        finally
        {
            if (null != oRAFile)
            {
                try
                {
                    oRAFile.close();
                }
                catch (IOException e)
                {
                    System.out
                            .println("close object of RandomAccessFile failed, IO Exception"
                                    + e.getStackTrace());
                }
            }

            if (null != oBIn)
            {
                try
                {
                    oBIn.close();
                }
                catch (IOException e)
                {
                    System.out
                            .println("close input stream of http connection failed, IO Exception"
                                    + e.getStackTrace());
                }
            }
        }
        System.out.println("The download thread "
                + this.iThreadId
                + " is ended at "
                + (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))
                        .format(new Date()));
    }

    public String getSFileURL()
    {
        return sFileURL;
    }

    public void setSFileURL(String fileURL)
    {
        sFileURL = fileURL;
    }

    public long getLStartIndex()
    {
        return lStartIndex;
    }

    public void setLStartIndex(long startIndex)
    {
        lStartIndex = startIndex;
    }

    public long getLEndIndex()
    {
        return lEndIndex;
    }

    public void setLEndIndex(long endIndex)
    {
        lEndIndex = endIndex;
    }

    public int getIThreadId()
    {
        return iThreadId;
    }

    public void setIThreadId(int threadId)
    {
        iThreadId = threadId;
    }

    public String getSFullFileName()
    {
        return sFullFileName;
    }

    public void setSFullFileName(String fullFileName)
    {
        sFullFileName = fullFileName;
    }

}
